package com.wtpaint.udp.test2;

import java.io.IOException;
import java.net.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * UDP搜索放，用于搜索
 */
public class UDPSearcher {
    private static final int LISTEN_PORT = 30000;


    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("UDPSearcher started.");

        Listener listener = listen();
        sendBroadcast();

        System.in.read();
        List<Device> devices = listener.getDeviceList();
        for (Device device : devices) {
            System.out.println("Device:" + device.toString());
        }
    }

    private static Listener listen() throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        Listener listener = new Listener(LISTEN_PORT, countDownLatch);
        listener.start();

        countDownLatch.await();
        return listener;
    }

    private static void sendBroadcast() throws IOException {
        System.out.println("UDPSearcher sendBroadcast started.");
        //作为搜索方系统自动分配端口
        DatagramSocket ds = new DatagramSocket();

        //构建发送数据
        String responseData = MessageCreator.buildWithPort(LISTEN_PORT);
        byte[] responseBytes = responseData.getBytes();
        DatagramPacket requestPack = new DatagramPacket(responseBytes,
                responseBytes.length);

        requestPack.setAddress(InetAddress.getByName("255.255.255.255"));
        requestPack.setPort(20000);
        //发送
        ds.send(requestPack);
        ds.close();

        System.out.println("UDPSearcher sendBroadcast Complete.");
    }

    private static class Device {
        int port;
        String ip;
        String sn;

        Device(int port, String ip, String sn) {
            this.port = port;
            this.ip = ip;
            this.sn = sn;
        }

        @Override
        public String toString() {
            return "Device{" +
                    "port=" + port +
                    ", ip='" + ip + '\'' +
                    ", sn='" + sn + '\'' +
                    '}';
        }
    }


    private static class Listener extends Thread {
        private final int listenPort;
        private final CountDownLatch countDownLatch;
        private final List<Device> deviceList = new ArrayList<>();
        private boolean done = false;
        private DatagramSocket ds = null;

        public Listener(int listenPort, CountDownLatch countDownLatch) {
            this.listenPort = listenPort;
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            super.run();
            countDownLatch.countDown();
            try {
                //作为搜索方系统自动分配端口
                ds = new DatagramSocket(listenPort);
                while (!done) {
                    //接收回送数据
                    final byte[] buf = new byte[512];
                    DatagramPacket receivePack = new DatagramPacket(buf, buf.length);
                    ds.receive(receivePack);
                    //打印信息
                    String ip = receivePack.getAddress().getHostAddress();
                    int port = receivePack.getPort();
                    int dataLen = receivePack.getLength();
                    String data = new String(receivePack.getData(), 0, dataLen);
                    System.out.println("UDPSearcher receive form ip :" + ip + " port:" + port + " data:" + data);

                    String sn = MessageCreator.parseSN(data);
                    if (null != sn) {
                        Device device = new Device(port, ip, sn);
                        deviceList.add(device);
                    }
                }
            } catch (Exception ignored) {
            } finally {
                close();
            }
            System.out.println("UDPSearcher listened end.");
        }

        private void close() {
            if (null != ds) {
                ds.close();
                ds = null;
            }
        }

        List<Device> getDeviceList() {
            done = true;
            close();
            return deviceList;
        }
    }
}
